#define GLM_SWIZZLE
#include "Camera.h"
#include <glm/gtc/matrix_transform.hpp>

mgl::Camera::Camera(const glm::vec3& position, const glm::vec3& look, const glm::vec3& up, float fov, int width, int height, float nearClip, float farClip) :
	m_position(position), m_look(look), m_up(up)
{
	m_right = glm::cross(look, up);
	glm::normalize(m_right);

	m_fov = fov;
	m_width = width;
	m_height = height;
	m_near = nearClip;
	m_far = farClip;
	//update
	update();
}

void mgl::Camera::rotate(const glm::vec3& axis, float radian)
{
	glm::mat4 rot(1.f);
	rot = glm::rotate(rot, radian, axis);
	m_look	= (rot * glm::vec4(m_look, 0.f	)).xyz();
	m_up	= (rot * glm::vec4(m_up, 0.f	)).xyz();
	m_right = (rot * glm::vec4(m_right, 0.f	)).xyz();
	//update
	m_view = glm::lookAt(m_position, m_position+m_look, m_up);
}

void mgl::Camera::move(const glm::vec3& direction, float distance)
{
	m_position += direction * distance;
	m_view = glm::lookAt(m_position, m_position+m_look, m_up);
}

void mgl::Camera::resize(int width, int heigt)
{
	m_width = width;
	m_height = heigt;
	m_persp = glm::perspective(m_fov, (float)m_width/(float)m_height, m_near, m_far);
}

void mgl::Camera::update()
{
	m_view = glm::lookAt(m_position, m_position+m_look, m_up);
	m_persp = glm::perspective(m_fov, (float)m_width/(float)m_height, m_near, m_far);
}

const glm::mat4& mgl::Camera::getMVP(const glm::mat4& modelMat)
{
	m_mvp = m_persp * m_view * modelMat;
	return m_mvp;
}

const glm::mat4& mgl::Camera::getMV(const glm::mat4& modelMat)
{
	m_mv = m_view * modelMat;
	return m_mv;
}
